package com.aijk.commons.utils;

import com.aijk.commons.exception.ErrorCodeException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.SAXReader;

import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

/**
 * @author chendw
 */
public class XMLUtil {

    private XMLUtil() {

    }

    /**
     * 将对象转成XML
     *
     * @param object
     * @return
     */
    public static String bean2xml(Object object) {
        return bean2xml(object, null);
    }


    /**
     * 将对象转成XML
     *
     * @param object   对象实例
     * @param paramMap 序列号参数 { Marshaller.JAXB_FORMATTED_OUTPUT:true , Marshaller.JAXB_ENCODING, "utf-8" }
     * @return
     */
    public static String bean2xml(Object object, Map<String, Object> paramMap) {
        StringWriter writer = new StringWriter();
        JAXBContext context;
        try {
            context = JAXBContext.newInstance(object.getClass());
            Marshaller marshaller = context.createMarshaller();
            if (paramMap == null) {
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
            } else {

                paramMap.forEach((key, val) -> {
                    try {
                        marshaller.setProperty(key, val);
                    } catch (PropertyException e) {
                        throw new ErrorCodeException(e);
                    }
                });
            }

            marshaller.marshal(object, writer);
        } catch (JAXBException e) {
            throw new ErrorCodeException(e);
        }

        return writer.getBuffer().toString();
    }


    /**
     * 将XML转成java对象
     *
     * @param xml   xml格式的字符串
     * @param clazz java对象
     * @return
     * @throws JAXBException
     */
    @SuppressWarnings("unchecked")
    public static <T> T xml2bean(String xml, Class<?> clazz) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Unmarshaller um = jaxbContext.createUnmarshaller();
        StreamSource streamSource = new StreamSource(new StringReader(xml));
        return (T) um.unmarshal(streamSource);
    }

    /**
     * 将XML转成java对象
     *
     * @param file
     * @param clazz
     * @return
     * @throws JAXBException
     */
    @SuppressWarnings("unchecked")
    public static <T> T xml2bean(File file, Class<?> clazz) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Unmarshaller um = jaxbContext.createUnmarshaller();
        return (T) um.unmarshal(file);
    }

    /**
     * 将字符串转为XML
     *
     * @param xml 字符串
     * @return
     * @throws DocumentException
     */
    public static Document parseXml(String xml) throws DocumentException {
        return DocumentHelper.parseText(xml);
    }

    /**
     * 根据XPATH获得节点内容
     *
     * @param xpath    xml节点路径
     * @param document xml文档
     * @return
     */
    public static String getElementByXPath(String xpath, Document document) {
        return document.selectSingleNode(xpath).getText();
    }

    /**
     * 加载XML文件
     *
     * @param path
     * @return
     */
    public static String load(String path) {
        SAXReader sr = new SAXReader();
        path = XMLUtil.class.getResource("/") + path;
        Document doc;
        try {
            doc = sr.read(path);
        } catch (DocumentException e) {
            throw new ErrorCodeException(e);
        }
        return doc.asXML();
    }

    /**
     * 从ClassPath加载XML文档
     *
     * @param path XML文件路径
     * @return
     */
    public static String loadFromClassPath(String path) {
        InputStream is = XMLUtil.class.getResourceAsStream("/" + path);
        Document doc;
        try {
            doc = new SAXReader().read(is);
        } catch (DocumentException e) {
            throw new ErrorCodeException(e);
        }
        return doc.asXML();
    }

}
